////////////////////////////
// OzZ Controls Core
//// Include OzZcontrols.h to your project instead
//// (c) Copyright by Daniel Bulla 2006

/** \mainpage
 *	\section flow Introducing what happens inside
 *	When "Init" was done, "Run" needs to be called every frame in order to update the layer.
 *	Init, caused the Interface to do something, usually the interface executed the script, so it had time to register all the hooks which define the behaviour and the look
 *	(and basically everything) of the layer. So the Interface is the modula that cares about the methode to get an behaving layer (how to read/interpret data in(to) the layer).
 *	Moreover Init cared about the right Renderer (how to bring the layer on the screen).
 *	At last it cared about the input (how to make the user react).
 *	In each frame the layer runs through each element and checks for it's registered hooks (onXXX) and calls them on demand using the Interface "HandleHook".
 *	This mechanism is used, to let the called hook be an first-class-value. If the interface would have to set functions to the elements on interface-start(-compiling)-time this would not be possible.
 *	
 */

#pragma once

#include "../OzZtypes.h"
#include "../OzZvisualizator.h"
#include "../OzZinterface.h"
#include "../OzZfunctionality.h"
#include "OzZLayer.h"
#include <PlugEngine.h>

//#include <vector>
//#include <string>
//#include <stack>
//#include <utility>

struct oc::Element;

namespace oc
{
	typedef std::pair<Element*, bool> FocParamPair;
	typedef std::stack<FocParamPair> FocStack;
}
/// The Main class.
/** A object of this class reflects the overlay.
 *	\todo: all the luafunctions as friends ?
 */	
class oc::OzZCore: public oc::CFunctionality, public oc::Layer
{

	bool		m_bInitialized;					///< indicates if the class is already initialized
	bool		m_bActive;						///< indicates if the class is ready-to-use

	char*		m_szWorkingDir;					///< saves the current directory.
												/**< allocated on initialisation, freed on unitialisation!
												 */

	Element*	m_pDesktop;						///< the root-element.
												/**< Here the tree of elements begins. This is the element, that is refered to
												 *	if you don't specify an element closer in a called function
												 *	\todo make the system don't know which element is the topmost for perfect recursion! Idea: give every element an "is null" flag, that indicates if it's children should refer to this element as NULL-element
												 */
				
	Element*	m_pKeyboardFocused;				///< the element, that has the keyboard focus \todo: is it needed? what to do about it also add a setZ function, so ne chain-focusing is needed!

	Element*	m_pPrevFocused;					///< used to unfocus
	FocStack	m_stackToFocus;					///< all elements, that got focused the last (rendering-) step
	///@name Input
	///@{
	Coord1D		*m_pMouseXrel, *m_pMouseYrel, *m_pMouseZrel,
				*m_pMouseXabs, *m_pMouseYabs, *m_pMouseZabs;///< hold input \deprecated \todo: hooks for input!

	bool*		m_pKeys;// [256]				///< field of 256 keystates \deprecated
	bool*		m_pKeysTrigger;					///< field of 256 bools, that trigger when a key is pressed \deprecated costs too much speed!

	bool*		m_pMouseButtons;//[8]			///< field of 8 mouse-button states \deprecated
	bool*		m_pMouseButtonsTrigger;			///< \sa m_pKeys	\deprecated
	char*		m_pszBuff;						///< used for buffered input \todo see if it's deprecated

	void		(*m_ShowMouse)(bool bShow);		///< callback-function that has to set mouse visible or invisble
	///@}
	CPluginContainer	plgContViz;				///< holds Visualistion-Plugins
	//CPluginContainer	plgContType;
	CPluginContainer	plgContInterface;		///< holds Interface-Plugins

						///	Invokes a Hook.
						/**	This Function is called whenever an action is requested from the Interface
						 *  \deprecated if pElem is NULL it's taken from luaindex -(params+1), it pops all the parameters and the pElem from stack!
						 */
	void			CallInterfaceHook(Element* pElem, HOOKID hook, const int params, const bool bKeepElem = false) const;

						/// Used internally for speedup \sa ?
	void			_PointsWhichLoop(AdvancedCollisionInfo** papRes, const Coord2D_si* const paPoints, const unsigned int uiNoOfPoints, const Element* const pElem, CollisionInfo* const paCIRes, Coord2D_si* const paPBuffer, bool bNext = false);

	CostumeMat*	m_pCMatBuff;										///< buffer for transformation \todo check if it's needed

	CVisualizator*		m_pViz;			/*OUT*/											///< pointer to the Visualization-Plugin
	CInterface*			m_pInterface;	/*OUT*/											///< pointer to the Controller-Plugin
	//Layer				m_Layer;		/*IN*/											///< container for the functions, the application will have to acces
	//CFunctionality		m_Func;			/*IN*/											///< container for the functions, the controller will have to acces

	void	Prepair();	/// \sa Invoked by Init() and OnResetDevice()
	void	CleanUp();	/// \sa Invoked by FinalCleanUp() and OnLostDevice()

protected:

//---------------- Layer --------
	void	Init(InitInfo* ii, char* renderer, char* interf);
	void	OnLostDevice();
	void	OnResetDevice();
	void	FinalCleanUp();	
	void	Reset();
	void	SetSize(Coord2D_si* rt);
	void	Run();
//---------------- /Layer --------
//---------------- Functioanlity --------
	void SimulateHookCall(const Element* const pTo, HOOKID hook);
	void EnableHook(const Element* const pFor, HOOKID hook);
	void DisableHook(const Element* const pFor, HOOKID hook);

	void PopParameter(PARAMETER* pParam);

	void PushParameter(void* pParam);

	Element*		AddElement(Element* pParent) const;
	void			DeleteElement(Element* pElem) const;
	void			FocusElement(const Element* const) const;
	Element*		GetFocusedElement() const;

	void			SetElementMember(		Element* const	pElem, void* ElementPaper::* pMember, void* pValue) const;
	void*			GetElementMember(const	Element* const	pElem, void* ElementPaper::* pMember) const;
	Element*		PointsOverWhich(AdvancedCollisionInfo** papResults, const Coord2D_si* const paPoints, const UINT uiNoOfPoints, const Element* const pElem =NULL);
	void			PointsOver(CollisionInfo* const paResults, Coord2D_si* const paPoints, const UINT uiNoOfPoints, const Element* const pElem, bool bCheckChildren) const;
	void			TransformPoints(Coord2D_si* const paResults, const Coord2D_si* const paPoints, const unsigned int uiNoOfPoints, const Element* const pFrom, const Element* const pTo) const;
//---------------- /Functioanlity --------

public:
	OzZCore();
	~OzZCore();
							/// Gets the visualizator
							/** \return visualizator
							 */
	const CVisualizator* GetViz() const;

	TransData m_TransData;///< used to track errors \depricated ?

							/// Mostly used intern
							/** It renders the frame from a given position down to it's children (or from the bottom up)
							 */
	void	RunFrom(Element* pElem, bool bUpdate=true);

							/// \todo no idea of this!
	void	UpdateVars() const;
};

struct oc::Element
{

	Element*		m_pParent;				///< the parent the elem belongs to
	Element*		m_pChildren;			///< points the first children (which has a Next pointer, so you can iterate)
	Element*		m_pNext;				///< next elem or NULL
	Element*		m_pPrev;				///< previous elem or NULL

	ElementPaper	m_RD;					///< the mainpart of the element

	CostumeMat*		m_pRender;				///< the finale rendering Matrix \todo introduce "Static element" (a rendering surface, that does not need to be rendered live)
private:
	friend OzZCore;
	Element()
	{}
};
